import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import requests
from django.conf import settings
import json
import logging
import hmac
import hashlib
import base64
import time
from urllib.parse import quote_plus
from datetime import datetime

logger = logging.getLogger(__name__)

def send_email(recipients, subject, content):
    """发送邮件"""
    try:
        msg = MIMEMultipart()
        msg['From'] = settings.EMAIL_HOST_USER
        msg['To'] = ', '.join(recipients)
        msg['Subject'] = subject

        msg.attach(MIMEText(content, 'html', 'utf-8'))

        with smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) as server:
            if settings.EMAIL_USE_TLS:
                server.starttls()
            server.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)
            server.send_message(msg)
        return True
    except Exception as e:
        logger.error(f"发送邮件失败: {str(e)}")
        raise

def send_sms(phone_numbers, content):
    """发送短信"""
    # 这里需要根据实际使用的短信服务商来实现
    # 示例使用通用的 HTTP 接口
    try:
        api_url = settings.SMS_API_URL
        api_key = settings.SMS_API_KEY
        
        for phone in phone_numbers:
            data = {
                'phone': phone,
                'content': content,
                'key': api_key
            }
            
            response = requests.post(api_url, json=data)
            response.raise_for_status()
            
        return True
    except Exception as e:
        logger.error(f"发送短信失败: {str(e)}")
        raise

def send_webhook(url, method, headers, data):
    """发送 Webhook 请求"""
    try:
        response = requests.request(
            method=method,
            url=url,
            headers=headers,
            json=data
        )
        response.raise_for_status()
        return True
    except Exception as e:
        logger.error(f"发送 Webhook 失败: {str(e)}")
        raise

def send_dingtalk(webhook_url, secret=None, content=""):
    """发送钉钉通知"""
    try:
        headers = {'Content-Type': 'application/json'}
        
        # 如果配置了加签，需要生成签名
        if secret:
            timestamp = str(round(datetime.now().timestamp() * 1000))
            string_to_sign = f"{timestamp}\n{secret}"
            hmac_code = hmac.new(
                secret.encode('utf-8'),
                string_to_sign.encode('utf-8'),
                digestmod=hashlib.sha256
            ).digest()
            sign = base64.b64encode(hmac_code).decode('utf-8')
            webhook_url = f"{webhook_url}&timestamp={timestamp}&sign={sign}"

        data = {
            "msgtype": "markdown",
            "markdown": {
                "title": "监控告警",
                "text": content
            }
        }
        
        response = requests.post(webhook_url, headers=headers, json=data)
        response.raise_for_status()
        return True
    except Exception as e:
        logger.error(f"发送钉钉通知失败: {str(e)}")
        raise

def send_feishu(webhook_url, secret=None, content=""):
    """发送飞书通知"""
    try:
        headers = {'Content-Type': 'application/json'}
        
        # 如果配置了加签，需要生成签名
        if secret:
            timestamp = str(round(datetime.now().timestamp()))
            string_to_sign = f"{timestamp}\n{secret}"
            hmac_code = hmac.new(
                secret.encode('utf-8'),
                string_to_sign.encode('utf-8'),
                digestmod=hashlib.sha256
            ).digest()
            sign = base64.b64encode(hmac_code).decode('utf-8')
            
            data = {
                "timestamp": timestamp,
                "sign": sign,
                "msg_type": "text",
                "content": {"text": content}
            }
        else:
            data = {
                "msg_type": "text",
                "content": {"text": content}
            }
        
        response = requests.post(webhook_url, headers=headers, json=data)
        response.raise_for_status()
        return True
    except Exception as e:
        logger.error(f"发送飞书通知失败: {str(e)}")
        raise

def send_serverchan(sckey, content=""):
    """发送Server酱通知"""
    try:
        url = f"https://sctapi.ftqq.com/{sckey}.send"
        data = {
            "title": "监控告警",
            "desp": content
        }
        
        response = requests.post(url, data=data)
        response.raise_for_status()
        return True
    except Exception as e:
        logger.error(f"发送Server酱通知失败: {str(e)}")
        raise

def send_wecom(corp_id, corp_secret, agent_id, content=""):
    """发送企业微信通知"""
    try:
        # 获取访问令牌
        token_url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corp_id}&corpsecret={corp_secret}"
        token_response = requests.get(token_url)
        access_token = token_response.json()['access_token']
        
        # 发送消息
        send_url = f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}"
        data = {
            "touser": "@all",
            "msgtype": "text",
            "agentid": agent_id,
            "text": {
                "content": content
            }
        }
        
        response = requests.post(send_url, json=data)
        response.raise_for_status()
        return True
    except Exception as e:
        logger.error(f"发送企业微信通知失败: {str(e)}")
        raise

def send_telegram(bot_token, chat_id, content=""):
    """发送Telegram通知"""
    try:
        url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
        data = {
            "chat_id": chat_id,
            "text": content,
            "parse_mode": "HTML"
        }
        
        response = requests.post(url, json=data)
        response.raise_for_status()
        return True
    except Exception as e:
        logger.error(f"发送Telegram通知失败: {str(e)}")
        raise

def send_alert_notification(notification, alert):
    """发送告警通知"""
    if not notification.is_active or alert.level not in notification.alert_levels:
        return False

    try:
        # 准备通知内容
        content = f"""
        告警级别: {alert.get_level_display()}
        设备: {alert.device.name}
        时间: {alert.created_at}
        内容: {alert.message}
        """

        if notification.type == 'email':
            return send_email(
                recipients=notification.config.get('recipients', []),
                subject=f"[监控告警] {alert.device.name}",
                content=content
            )
        elif notification.type == 'sms':
            return send_sms(
                phone_numbers=notification.config.get('phone_numbers', []),
                content=f"[监控告警] {content}"
            )
        elif notification.type == 'webhook':
            data = {
                'level': alert.level,
                'device': alert.device.name,
                'message': alert.message,
                'time': alert.created_at.isoformat()
            }
            return send_webhook(
                url=notification.config.get('url'),
                method=notification.config.get('method', 'POST'),
                headers=notification.config.get('headers', {}),
                data=data
            )
        elif notification.type == 'dingtalk':
            return send_dingtalk(
                webhook_url=notification.config.get('webhook_url'),
                secret=notification.config.get('secret'),
                content=content
            )
        elif notification.type == 'feishu':
            return send_feishu(
                webhook_url=notification.config.get('webhook_url'),
                secret=notification.config.get('secret'),
                content=content
            )
        elif notification.type == 'serverchan':
            return send_serverchan(
                sckey=notification.config.get('sckey'),
                content=content
            )
        elif notification.type == 'wecom':
            return send_wecom(
                corp_id=notification.config.get('corp_id'),
                corp_secret=notification.config.get('corp_secret'),
                agent_id=notification.config.get('agent_id'),
                content=content
            )
        elif notification.type == 'telegram':
            return send_telegram(
                bot_token=notification.config.get('bot_token'),
                chat_id=notification.config.get('chat_id'),
                content=content
            )
    except Exception as e:
        logger.error(f"发送告警通知失败: {str(e)}")
        return False

def send_test_notification(notification):
    """发送测试通知"""
    test_content = "这是一条测试通知，请忽略。"
    
    try:
        if notification.type == 'email':
            return send_email(
                recipients=notification.config.get('recipients', []),
                subject="[测试] 监控系统告警通知",
                content="这是一条测试通知，请忽略。"
            )
        elif notification.type == 'sms':
            return send_sms(
                phone_numbers=notification.config.get('phone_numbers', []),
                content="[测试] 监控系统告警通知"
            )
        elif notification.type == 'webhook':
            data = {
                'type': 'test',
                'message': '这是一条测试通知，请忽略。',
                'time': datetime.now().isoformat()
            }
            return send_webhook(
                url=notification.config.get('url'),
                method=notification.config.get('method', 'POST'),
                headers=notification.config.get('headers', {}),
                data=data
            )
        elif notification.type == 'dingtalk':
            return send_dingtalk(
                webhook_url=notification.config.get('webhook_url'),
                secret=notification.config.get('secret'),
                content=test_content
            )
        elif notification.type == 'feishu':
            return send_feishu(
                webhook_url=notification.config.get('webhook_url'),
                secret=notification.config.get('secret'),
                content=test_content
            )
        elif notification.type == 'serverchan':
            return send_serverchan(
                sckey=notification.config.get('sckey'),
                content=test_content
            )
        elif notification.type == 'wecom':
            return send_wecom(
                corp_id=notification.config.get('corp_id'),
                corp_secret=notification.config.get('corp_secret'),
                agent_id=notification.config.get('agent_id'),
                content=test_content
            )
        elif notification.type == 'telegram':
            return send_telegram(
                bot_token=notification.config.get('bot_token'),
                chat_id=notification.config.get('chat_id'),
                content=test_content
            )
    except Exception as e:
        logger.error(f"发送测试通知失败: {str(e)}")
        raise 